﻿using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Windows.Forms;

namespace Library.Winform.Hooks {

  /// <summary>
  /// Mouse buttons that can be pressed
  /// </summary>
  public enum MouseButton {
    None = 0x0,
    Left = 0x2,
    Right = 0x8,
    Middle = 0x20
  }

  /// <summary>
  /// Operations that simulate mouse events
  /// </summary>
  public static class MouseSimulator {

    #region Windows API Code
    [DllImport("user32.dll")]
    static extern void mouse_event(int flags, int dX, int dY, int buttons, int extraInfo);

    const int MouseeventfMove = 0x1;
    const int MouseeventfLeftdown = 0x2;
    const int MouseeventfLeftup = 0x4;
    const int MouseeventfRightdown = 0x8;
    const int MouseeventfRightup = 0x10;
    const int MouseeventfMiddledown = 0x20;
    const int MouseeventfMiddleup = 0x40;
    const int MouseeventfWheel = 0x800;
    const int MouseeventfAbsolute = 0x8000;

    #endregion



    #region Methods

    /// <summary>
    /// Press a mouse button down
    /// </summary>
    /// <param name="button"></param>
    public static void MouseDown(MouseButton button) {
      mouse_event(((int)button), 0, 0, 0, 0);
    }

    /// <summary>
    /// Press a mouse button down
    /// </summary>
    /// <param name="button"></param>
    public static void MouseDown(MouseButtons button) {
      switch (button) {
        case MouseButtons.Left:
          MouseDown(MouseButton.Left);
          break;
        case MouseButtons.Middle:
          MouseDown(MouseButton.Middle);
          break;
        case MouseButtons.Right:
          MouseDown(MouseButton.Right);
          break;
      }
    }

    /// <summary>
    /// Let a mouse button up
    /// </summary>
    /// <param name="button"></param>
    public static void MouseUp(MouseButton button) {
      mouse_event(((int)button) * 2, 0, 0, 0, 0);
    }

    /// <summary>
    /// Let a mouse button up
    /// </summary>
    /// <param name="button"></param>
    public static void MouseUp(MouseButtons button) {
      switch (button) {
        case MouseButtons.Left:
          MouseUp(MouseButton.Left);
          break;
        case MouseButtons.Middle:
          MouseUp(MouseButton.Middle);
          break;
        case MouseButtons.Right:
          MouseUp(MouseButton.Right);
          break;
      }
    }

    /// <summary>
    /// Click a mouse button (down then up)
    /// </summary>
    /// <param name="button"></param>
    public static void Click(MouseButton button) {
      MouseDown(button);
      MouseUp(button);
    }

    /// <summary>
    /// Click a mouse button (down then up)
    /// </summary>
    /// <param name="button"></param>
    public static void Click(MouseButtons button) {
      switch (button) {
        case MouseButtons.Left:
          Click(MouseButton.Left);
          break;
        case MouseButtons.Middle:
          Click(MouseButton.Middle);
          break;
        case MouseButtons.Right:
          Click(MouseButton.Right);
          break;
      }
    }

    /// <summary>
    /// Double click a mouse button (down then up twice)
    /// </summary>
    /// <param name="button"></param>
    public static void DoubleClick(MouseButton button) {
      Click(button);
      Click(button);
    }

    /// <summary>
    /// Double click a mouse button (down then up twice)
    /// </summary>
    /// <param name="button"></param>
    public static void DoubleClick(MouseButtons button) {
      switch (button) {
        case MouseButtons.Left:
          DoubleClick(MouseButton.Left);
          break;
        case MouseButtons.Middle:
          DoubleClick(MouseButton.Middle);
          break;
        case MouseButtons.Right:
          DoubleClick(MouseButton.Right);
          break;
      }
    }

    /// <summary>
    /// Roll the mouse wheel. Delta of 120 wheels up once normally, -120 wheels down once normally
    /// </summary>
    /// <param name="delta"></param>
    public static void MouseWheel(int delta) {

      mouse_event(MouseeventfWheel, 0, 0, delta, 0);

    }

    ///// <summary>
    ///// Show a hidden current on currently application
    ///// </summary>
    //public static void Show() {
    //  ShowCursor(true);
    //}

    ///// <summary>
    ///// Hide mouse cursor only on current application's forms
    ///// </summary>
    //public static void Hide() {
    //  ShowCursor(false);
    //}

    #endregion

  }

}
